home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zcpp_jae.zip / PAPER.TXT < prev    next >
Text File  |  1991-04-29  |  35KB  |  826 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.                       **** EARLY DRAFT ****
  8.  
  9.  
  10.            A Portable Implementation of Parameterized
  11.        Templates Using A Sophisticated C++ Macro Facility
  12.  
  13.  
  14.                       **** EARLY DRAFT ****
  15.  
  16.  
  17.  
  18.                           Mary Fontana
  19.                            LaMott Oren
  20.  
  21.                  Texas Instruments Incorporated
  22.                      Computer Science Center
  23.                            Dallas, TX
  24.  
  25.  
  26.                           Martin Neath
  27.  
  28.                  Texas Instruments Incorporated
  29.                   Information Technology Group
  30.                            Austin, TX
  31.  
  32.  
  33.                             ABSTRACT
  34.  
  35.           The Texas Instruments C++ Object-Oriented  Library
  36.      (COOL) is a collection of classes, templates and macros
  37.      for use by C++  programmers  writing  complex  applica-
  38.      tions.   Parameterized  types,  symbolic  computing and
  39.      exception handling are  significant  features  of  COOL
  40.      which improve the development capabilities available to
  41.      the programmer.  These features are implemented in COOL
  42.      with  a  sophisticated  C++ macro facility.  This paper
  43.      describes the COOL macro facility, discusses  how  sup-
  44.      port  for parameterized templates is built upon it, and
  45.      provides details of  two  programmer  interfaces  (both
  46.      implemented) for easy use of parameterized templates in
  47.      application programs.
  48.  
  49.  
  50.  
  51. 1.  Introduction
  52. The Texas Instruments C++ Object-Oriented  Library  (COOL)  is  a
  53. collection  of  classes, templates and macros for use by C++ pro-
  54. grammers writing complex applications. It is  designed  to  raise
  55. the  level  of abstraction for the programmer in order to facili-
  56. tate concentration on the problem  domain,  not  on  implementing
  57. base  data  structures,  macros,  and classes.  In addition, COOL
  58.  
  59.                                       -1-
  60. provides a system-independent software platform on top  of  which
  61. applications are built. Parameterized templates, symbolic comput-
  62. ing, and exception handling  are  significant  features  of  COOL
  63. which  substantially  improve the development capabilities avail-
  64. able to the C++ programmer.  We wished to provide  these  facili-
  65. ties in a compiler- and machine-independent manner across several
  66. hardware platforms.  We examined the macro definition and  expan-
  67. sion  mechanism  found in standard C-preprocessors and determined
  68. that it is not sufficient for implementing these features.  As  a
  69. result,  we  developed  the COOL macro facility to allow the pro-
  70. grammer to define powerful extensions to the C++  language  in  a
  71. seamless  and  unobtrusive manner.  This macro facility is imple-
  72. mented as an extension to a standard  C  preprocessor  [1].   The
  73. modifications made to the preprocessor are both portable and com-
  74. piler independent.  This  paper  describes  this  enhanced  macro
  75. facility, discusses how parameterized templates is built upon it,
  76. and provides details of two programmer  interfaces  (both  imple-
  77. mented) for easy use of parameterized templates.  For an overview
  78. of COOL see the paper, COOL - A C++ Object-Oriented Library  [2].
  79. For  complete  details,  see  the reference document, COOL User's
  80. Manual [3].
  81.  
  82. 2.  The COOL Preprocessor and the defmacro Keyword
  83. Many C++ language implementations separate the  preprocessor  and
  84. compiler  functions  into two separate programs. Others, (such as
  85. the Glockenspiel C++ language system), combine  the  preprocessor
  86. and compiler into one step. Since we needed a portable utility to
  87. massage C++ source code that works under both scenarios and  exe-
  88. cutes  after  include  files and standard preprocessor directives
  89. have been expanded, but before the  C++  compiler  itself  begins
  90. parsing,  we  decided  to  modify a C-preprocessor to support the
  91. COOL C++ language extensions.  Thus,  the  COOL  preprocessor  is
  92. derived  from  and based upon a public domain C-preprocessor (the
  93. DECUS C preprocessor) made available by the DEC User's group  and
  94. supplied  on the X11R3 source tape from MIT. It has been modified
  95. to comply with the draft ANSI C specification with the  exception
  96. that trigraph sequences are not supported.
  97.  
  98. The draft-proposed ANSI C standard indicates that extensions  and
  99. changes to the language or features implemented in a preprocessor
  100. or compiler should be made by using  the  #pragma  keyword.   The
  101. COOL  preprocessor  recognizes a #pragma defmacro declaration and
  102. is the single hook through  which  features  such  as  the  class
  103. macro, parameterized templates, and polymorphic enhancements have
  104. been implemented. The defmacro keyword provides a way  to  define
  105. and  execute  arbitrary filter programs or macro expanders on C++
  106. code fragments.  The syntax of the defmacro declaration is:
  107.  
  108.         #pragma defmacro name "program" options
  109.         #pragma defmacro name <program> options
  110.  
  111. where name is the name of the macro, program is either  the  name
  112. of  an  executable  file  or the name of an internal preprocessor
  113. function which implements the macro expansion,  and  options  are
  114. any combination of the following optional parameters:
  115.  
  116.  
  117.  
  118.                                       -2-
  119.  
  120.         recursive       - the macro may be recursively expanded.
  121.         expanding       - the input to the macro is expanded.
  122.         delimiter= x    - the default delimiter (semi-colon) is
  123.                           replaced with x.
  124.  
  125. Unknown options are passed as arguments  to  the  macro  expander
  126. named  program.  This provides the necessary handle through which
  127. COOL functions and language extensions  can  be  identified.  For
  128. example,  the  MACRO  and template keywords are defined in a top-
  129. level header file with:
  130.  
  131.         #pragma defmacro MACRO "macro" delimiter=} recursive
  132.         #pragma defmacro template "template" delimiter=}
  133.  
  134. The implementation of the macro expander program  may  be  either
  135. external  or  internal  to  the  preprocessor.   Fundamental COOL
  136. macro-expanders are implemented internal to the COOL preprocessor
  137. for  the sole reason of providing a more efficient execution pro-
  138. file to reduce compile time for the application programmer.  When
  139. the  preprocessor encounters a defmacro declaration in the source
  140. code, it searches first for an executable file named  program  on
  141. the  same search path as that used for include files.  If a match
  142. is not found, it then searches for program in an internal prepro-
  143. cessor  function  table.  If a match is still not found, an error
  144. is reported indicating that  the  macro  expander  could  not  be
  145. found.  This search order allows an internal preprocessor defini-
  146. tion to be overridden by an external one.
  147.  
  148. When a defmacro name is successfully recognized, the name and all
  149. following  characters  upto and including the delimiter character
  150. (including all matching and nested levels of {} [] ()  <>  ""  ''
  151. and  comments  found  along  the way) are piped into the standard
  152. input of the macro expander program.  The expander  program  per-
  153. forms  whatever function(s) is appropriate and the resulting mas-
  154. saged character stream is piped back onto the standard output  of
  155. the  macro  expander.  This output stream is scanned as new input
  156. by the preprocessor for any  further  processing  that  might  be
  157. necessary.  The original text in the source file is replaced with
  158. the preprocessor output before being sent onto the C++  compiler.
  159. The expansion replacing a defmacro name in the source code is C++
  160. 2.0 syntax acceptable to any conforming C++  translator  or  com-
  161. piler [4].
  162.  
  163. 3.  The MACRO Keyword
  164. The COOL MACRO keyword provides a  powerful  and  flexible  macro
  165. capability  used  to  implement and simplify many of the features
  166. and functions contained in the library. A  defmacro  named  MACRO
  167. (all  uppercase) provides an enhanced #define macro that supports
  168. multi-line, arbitrary length, nested  macros  and  cpp-directives
  169. with  positional,  optional,  optional keyword, required keyword,
  170. rest, and body arguments. MACRO has the following syntax:
  171.  
  172.     MACRO name ( parmlist ) { body }
  173.     parmlist  :=
  174.         [KEY: | REST: | BODY:] identifier [= identifier] [, parmlist]
  175.  
  176.  
  177.                                       -3-
  178. where name is the name of the macro, parmlist is a list of param-
  179. eters  separated  by  commas, and body is the code which replaces
  180. the MACRO reference.  The  parmlist  specification  allows  posi-
  181. tional,  keyword,  rest,  and body parameters to be identified by
  182. the programmer.  The positional and  keyword  parameters  may  be
  183. required or optional. Optional parameters are supported by use of
  184. an equal sign  followed  by  an  identifier  that  specifies  the
  185. default  value.  All the optional positional parameters must fol-
  186. low all of the required positional ones.
  187.  
  188. When KEY: is specified in the parmlist, all parameters which fol-
  189. low  are  keyword  parameters.   Keyword parameters are position-
  190. independent parameters.  A keyword parameter is provided a  value
  191. in  an argument list by supplying the keyword name followed by an
  192. equal sign and the argument value.  REST: in the  parmlist  indi-
  193. cates  that  the remaining parameters are referenced by one named
  194. identifier.  An optional equal sign  followed  by  an  identifier
  195. sets  the  identifier after the equal sign to the number of argu-
  196. ments remaining.  Finally, BODY: in the parmlist  indicates  that
  197. the parameter which follows is expanded to include all the source
  198. code within the braces after the MACRO call.  This is useful  for
  199. passing a source code fragment onto other nested MACROs. Examples
  200. of these three types of arguments are given below.
  201.  
  202. 3.1.  MACRO Examples
  203. The following examples show some of the power and flexibility  of
  204. MACRO.   This  first  example uses both positional parameters and
  205. keyword parameters.
  206.  
  207.         MACRO set_val (size, value=NULL, KEY: low=0, high) {
  208.             init (size, value, low, (high-low))
  209.         }
  210.  
  211. set_val has three  parameters:  size  is  a  required  positional
  212. parameter,  value is an optional positional parameter that if not
  213. specified in a particular call has a default value of  NULL,  low
  214. is  an  optional keyword parameter with a default value of 0, and
  215. high is a required  keyword  parameter.   In  this  example,  the
  216. expansion  calls  the function init with four arguments. The fol-
  217. lowing shows several expansions of set_val.
  218.  
  219.     set_val (0, high=20)            ---->      init (0, NULL, 0, (20-0));
  220.     set_val (0, low=5, high=15)     ---->      init (0, NULL, 5, (15-5));
  221.     set_val (1, 2, high=25)         ---->      init (1, 2, 0, (25-0));
  222.  
  223. The next example uses the REST: parameter.  Note that  there  are
  224. two  MACROs defined: build_table calls build_table_internal to do
  225. most of the work.
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.                                       -4-
  237.  
  238.         MACRO build_table (name, REST: rest) {
  239.             char* name[] = { build_table_internal(rest) NULL}
  240.         }
  241.  
  242.         MACRO build_table_internal (first, REST: rest=count) {
  243.             #first,
  244.             #if count
  245.             build_table_internal (rest)
  246.             #endif
  247.         }
  248.  
  249. build_table has two parameters: name is the name of the table  of
  250. char*'s   and   rest  refers  to  all  the  remaining  arguments.
  251. build_table calls build_table_internal passing its rest argument.
  252. Note  that this call is embedded within the initialization braces
  253. of the table and is followed by a NULL. In  build_table_internal,
  254. first  is  set to the first argument of the rest argument list in
  255. the invoking macro call, and the remaining  count  arguments  are
  256. left  in  rest. build_table_internal uses the ANSI # character on
  257. first to double quote the value. A conditional clause tests count
  258. to  see  if there are remaining arguments.  If count is non-zero,
  259. the macro is called recursively  with  the  remaining  arguments.
  260. When there are no more arguments, build_table regains control and
  261. appends the NULL character and closing brace  to  the  result  of
  262. build_table_internal.
  263.  
  264. A sample use of build_table is shown below to illustrate the con-
  265. struction   of   a  NULL-terminated  table  containing  character
  266. strings.  The first line shows the  macro  call  and  the  second
  267. shows the resulting expansion.
  268.  
  269.         build_table (table, 1,2,3,4,5,6,7);
  270.  
  271. expands to:
  272.  
  273.         char* table[] = {"1", "2", "3", "4", "5", "6", "7", NULL};
  274.  
  275. This last example uses the BODY: parameter and also takes  advan-
  276. tage  of the current position feature found in the COOL container
  277. classes [2]. This is used to implement  a  general  purpose  loop
  278. macro similar to that found in Common LISP [5].
  279.  
  280.         MACRO LOOP (type, identifier, object, BODY: body) {
  281.             { type identifier;
  282.               for ( object.reset(); object.next(); ) {
  283.                 identifier = object.value();
  284.                 body
  285.               }
  286.             }
  287.         }
  288.  
  289. LOOP has four parameters: type is the type of each element  in  a
  290. container  class  (such  as,  int),  identifier  is the name of a
  291. variable to be declared of the given type, object is the name  of
  292. a container class instance, and body is the body of code to apply
  293. on each element in the container object.  A specific example  for
  294.  
  295.                                       -5-
  296. the parameterized List<int> class is shown below.
  297.  
  298.         extern List<int> list1;
  299.         LOOP (int, var1, list1) { cout << var1; }
  300.  
  301. expands to:
  302.  
  303.         extern List<int> list1;
  304.         { int var1;
  305.           for ( list1.reset(); list1.next(); )  {
  306.             var1 = list1.value();
  307.             cout << var1;
  308.           }
  309.         }
  310.  
  311. In this example, list1 is an instance of  List<int>  which  is  a
  312. container class representing a list of integers.  LOOP takes this
  313. list object and iterates through the elements, assigning each  to
  314. a  temporary  integer  variable var1 and printing its value.  The
  315. net result will print all elements in the list.
  316.  
  317. 4.  COOL Parameterized Templates
  318. One of the main uses of the COOL macro facility is the  implemen-
  319. tation   of   template,  DECLARE  and  IMPLEMENT  for  supporting
  320. parameterized templates.  The syntax of the template  grammar  is
  321. that as specified by Stroustrup in his paper, Parameterized Types
  322. for C++ [6]. COOL fully implements this functionality  such  that
  323. there  will be minimal source code conversion necessary when this
  324. feature is finally implemented in the C++  language.   COOL  pro-
  325. vides  templates  for a number of parameterized classes (such as,
  326. Range and Iterator)  and  container  classes  (such  as,  Vector,
  327. List,  Binary_Tree  and  Hash_Table)  which are described in COOL
  328. User's Guide [3].
  329.  
  330. 4.1.  The template Keyword
  331. The template keyword provides a mechanism for defining parameter-
  332. ized classes.  A parameterized class is a type-independent class.
  333. A typical use is a container class where the  type  of  the  con-
  334. tained object is specified at compile-time.  For example, vectors
  335. can be declared to hold a specific type of element,  such  as,  a
  336. vector  of  integers  or  a  vector  of  doubles,  from  a single
  337. parameterized class, Vector<type>.
  338.  
  339. A template is divided into the declarative part and the implemen-
  340. tation  part  of  a  class.   The declarative part may occur many
  341. times in an application and is analogous to  including  a  header
  342. file  for  a  class  which  contains the class definition and its
  343. inline member functions.  The implementation part is analogous to
  344. the  file  that  contains the source code implementing the member
  345. and friend functions of the class.  COOL provides four variations
  346. of template for these two parts.
  347.  
  348.  
  349.     template <class type [, parms]> class name<type> { class_description };
  350.          Defines the class template for the declarative  part
  351.          of the name class.
  352.  
  353.  
  354.                                       -6-
  355.     template   <class   type   [,   parms]>   inline   result
  356.     name<type>::function { ... };
  357.          Defines an inline member function for  the  declara-
  358.          tive part of the name class.
  359.  
  360.     template    <class     type     [,     parms]>     result
  361.     name<type>::function { ... };
  362.          Defines a member  function  for  the  implementation
  363.          part of the name class.
  364.  
  365.     template <class type [, parms]> name { anything };
  366.          Defines anything else associated with a template for
  367.          the name class.
  368.  
  369. This form is used to define such things  as  typedefs  or  friend
  370. functions  of  a  parameterized  class.   When this form is found
  371. before the class template, the contents are expanded  before  the
  372. class  definition.   When this form is found after the class tem-
  373. plate, the contents are expanded as part of the class implementa-
  374. tion.   Note that this form is not part of the parameterized type
  375. syntax described by Stroustrup [6].  Rather, it is  something  we
  376. found  lacking  in the original proposal and found very useful in
  377. several COOL container classes for defining predicate  types  for
  378. the  class.  Another  use  of  this  form is to provide automatic
  379. declarations of nested parameterized classes, that is, to declare
  380. a  parameterized  class  for  a  class  template  which is itself
  381. derived from another parameterized class template.
  382.  
  383. Each variation of template allows additional optional  parameters
  384. with the following syntax:
  385.  
  386.         parms ::= type name [= value] [, parms]
  387.  
  388. where type is the type of the parameter, (such as, class or int);
  389. name  is  the name of the parameter that is substituted when tem-
  390. plate is expanded; and value is the default  value  of  parameter
  391. name.
  392.  
  393. The  following  is  an  example  of  template  for   the   class,
  394. Vector<type>.
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.                                       -7-
  414.  
  415.     template <class Type> Vector {          // predicate functions
  416.         typedef int (*Vector_Type##_Predicate) (const Type&, const Type&);
  417.         typedef Boolean (*Vector_Type##_Compare) (const Type&, const Type&);
  418.     };
  419.  
  420.  
  421.     template <class Type> class Vector<Type> {  // Parameterized Vector class
  422.       private:
  423.         Type* v;                                // Vector of pointer to Type
  424.         int num_elements;                       // Element count
  425.         int size;                               // Size of vector object
  426.       public:
  427.         Vector<Type> ();                        // Empty constructor
  428.         Vector<Type> (int);                     // Constructor with size
  429.         Vector<Type> (const Vector<Type>&);     // Constructor with reference
  430.         ~Vector<Type> ();                       // Destructor
  431.         inline Type& operator[](int n);         // Operator[] overload for Type
  432.  
  433.         ...                                     // ... other member functions
  434.     };
  435.  
  436.  
  437.     template <class Type>                       // Overload operator []
  438.     inline Type& Vector<Type>::operator[] (int n) {
  439.         return this->v[n];
  440.     }
  441.  
  442.  
  443.     template <class Type>                       // Constructor with size
  444.     Vector<Type>::Vector<Type> (int n) {
  445.         this->v = new Type[n];
  446.         this->size = n;
  447.         this->num_elements = 0;
  448.     }
  449.  
  450.     ...                                         // ... other member functions
  451.  
  452.  
  453. 4.2.  An Initial Programmer Interface: DECLARE and IMPLEMENT
  454. As stated earlier,  a  template  for  a  parameterized  class  is
  455. divided  into  a declarative part and an implementation part.  In
  456. our first attempt at implementing parameterized template support,
  457. the  programmer  creates instances of a parameterized class using
  458. DECLARE to expand the declarative part and  IMPLEMENT  to  expand
  459. the implementation part.  DECLARE defines the parameterized class
  460. for a specific type and IMPLEMENT generates the member  functions
  461. supporting  this  type-specific  class.   DECLARE must be used in
  462. every file that includes or makes use of the parameterized class.
  463. IMPLEMENT must be used only once in the application for each type
  464. over which the class is parameterized; otherwise the linker  will
  465. generate  errors about multiple versions of the same member func-
  466. tions.  For example, to create a vector of doubles, the following
  467. would be used:
  468.  
  469.  
  470.  
  471.  
  472.                                       -8-
  473.  
  474.         #include <Vector.h>
  475.         DECLARE Vector<double>;
  476.         IMPLEMENT Vector<double>;
  477.         Vector<double> vs(30);
  478.  
  479. DECLARE expands to code which defines a vector class  of  doubles
  480. and  its  associated inline member functions.  IMPLEMENT causes a
  481. class definition with its associated member functions to be  gen-
  482. erated  and expanded in the file.  When compiled, this causes the
  483. class Vector_double to be declared and defined. One  drawback  of
  484. the  use of IMPLEMENT, however, is the fact that the entire class
  485. with all its member functions is generated and  linked  into  the
  486. program  image,  even  if the programmer only requires the use of
  487. two or three member functions. This problem can be avoided by the
  488. use  of  the COOL C++ Control Program (CCC) discussed below. Con-
  489. tinuing with the example above, the template for the Vector<type>
  490. class for doubles would expand to the following code:
  491.  
  492.                                             // predicate functions
  493.     typedef int (*Vector_double_Predicate) (const double&, const double&);
  494.     typedef Boolean (*Vector_double_Compare) (const double&, const double&);
  495.  
  496.  
  497.     class Vector_double {                   // Parameterized Vector class
  498.     private:
  499.         double* v;                          // Vector of pointer to double
  500.         int num_elements;                   // Element count
  501.         int size;                           // Size of vector object
  502.     public:
  503.         Vector_double ();                   // Empty constructor
  504.         Vector_double (int);                // Constructor with size
  505.         Vector_double (const Vector_double&); // Constructor with reference
  506.         ~Vector_double ();                  // Destructor
  507.         inline double& operator[](int n);   // Operator[] overload for double
  508.  
  509.         ...                                 // ... other member functions ...
  510.     };
  511.  
  512.  
  513.                                             // Overload operator []
  514.     inline double& Vector_double::operator[] (int n) {
  515.         return this->v[n];
  516.     }
  517.  
  518.                                             // Constructor with size
  519.     Vector_double::Vector_double (int n) {
  520.         this->v = new double[n];
  521.         this->size = n;
  522.         this->num_elements = 0;
  523.     }
  524.  
  525.      ...                                    // ... other member functions ...
  526.  
  527.     Vector_double vs(30);
  528.  
  529. Declarations of nested parameterized types and the  use  of  non-
  530.  
  531.                                       -9-
  532. type  arguments  in a template definition are also supported. For
  533. example, it is possible to declare a vector of  vectors  of  ints
  534. with  Vector<Vector<int>>.  In addition, a class template derived
  535. from another class template is supported, that is, a type parame-
  536. ter  in  one  template class can be used to declare another class
  537. template of that type.  For example, the COOL  Association<T1,T2>
  538. class  is  a  parameterized  container  class that takes two type
  539. arguments, T1 and T2.  The header file for  this  class  has  the
  540. following templates.
  541.  
  542.     template <class T1, T2> Association {
  543.         DECLARE Pair<T1, T2>;           // Declare Pair object type
  544.         DECLARE Vector<Pair<T1, T2>>;   // Declare Vector of Pairs
  545.     }
  546.  
  547.     ...                                 // ...
  548.     // Association<T1,T2> class definition here
  549.  
  550.  
  551.  
  552.     template <class T1, T2> Association {
  553.         IMPLEMENT Pair<T1, T2>;
  554.         IMPLEMENT Vector<Pair<T1, T2>>;
  555.     }
  556.  
  557. By   using   template   in   this   manner,   DECLARE   for   the
  558. Association<T1,T2> class invokes DECLARE on the correct types for
  559. the Pair<T1,T2> and Vector<Type>  classes.   Likewise,  IMPLEMENT
  560. for  the  Association<T1,T2>  class  invokes  IMPLEMENT  for  the
  561. Pair<T1,T2> and Vector<Type> classes.
  562.  
  563. Non-type arguments as template parameters  are  used  to  provide
  564. guidelines  to  be used when a template is expanded. For example,
  565. the N_Tree<Node,Type,nchild> class in COOL takes as  arguments  a
  566. node  type  (either  static  or  dynamic),  a type specifying the
  567. value-type each node will hold, and an  argument  that  specifies
  568. the  number  of  initial  subtrees  (or children) each node is to
  569. have.  The node argument is itself the name  of  a  parameterized
  570. class and a nested parameterized template definition is automati-
  571. cally generated based upon the supplied  type  and  number  argu-
  572. ments. As such, a single template can be used to generate several
  573. different classes with different behaviors and features.
  574.  
  575. 4.3.  A Revised Programmer Interface: COOL  C++  Control  Program
  576. (CCC)
  577. The DECLARE and IMPLEMENT macros discussed above were  the  first
  578. programmer  interface implemented for parameterized template sup-
  579. port.  We soon discovered, however,  that  this  macro  expansion
  580. mechanism  had two serious problems. First, the type over which a
  581. class was parameterized would have to support all operators  used
  582. in  the template, even if not applicable or needed.  For example,
  583. the COOL List<Type> class has several member functions  that  use
  584. operator<.  However,  if  what  the programmer needs is a list of
  585. window objects and does not ever use List<Type> member  functions
  586. that  require  operator<,  compile-time errors from the offending
  587. functions that got  macro-expanded  are  nevertheless  generated.
  588. Second,  With  the simplistic linkers available on many operating
  589.  
  590.                                      -10-
  591. systems today, an application gets all of these member  functions
  592. linked into the executable image.  Typically, an application uses
  593. only a small percentage of the member functions of  a  parameter-
  594. ized  class.   The  remaining unused member functions are useless
  595. overhead, increasing program size and memory requirements.
  596.  
  597. A revised programmer interface for  parameterized  templates  was
  598. implemented  to  resolve  these problems and centers around a new
  599. program to be used as the main interface between the user and the
  600. preprocessor/compiler  in a make file. This program, the COOL C++
  601. Control program (CCC), augments the standard CC script.  For most
  602. operations,  user  options  and command line arguments are passed
  603. straight through to the underlying CC program.  However, when the
  604. -X  option is specified, the CCC program goes to work in the fol-
  605. lowing manner.  As Stroustrup[6] suggested, -X"Foo<Bar>" is  used
  606. on  the  command  line  to  indicate that the programmer wants to
  607. parameterize class Foo<Type>  over  some  type  Bar.   Additional
  608. options  for  include file search path and a user-defined library
  609. archive are required as described below.  CCC  finds  the  header
  610. file(s)  implementing  class  Foo  and type Bar, then proceeds to
  611. define that type for the compiler.  It then fractures the  imple-
  612. mentation  of  this  new  type along template boundaries, placing
  613. each non-inline member function in a separate source  file,  com-
  614. piling  it,  and  putting  the  resulting  object file in a user-
  615. specified library archive.   If  a  particular  operator  is  not
  616. defined  for  the  type over which the class is parameterized (as
  617. with the example of operator< above), a compile  time  error  for
  618. that  one file is generated.  However, the remaining member func-
  619. tions, one in each fractured template,  are  still  compiled  and
  620. added to the user library.
  621.  
  622. For each parameterized class in an application, CCC fractures the
  623. parameterized class definition along template boundaries, causing
  624. each template specifying a member function of  the  parameterized
  625. class to be compiled into a separate object file.  These separate
  626. object files are then added  to  an  application-specific  object
  627. library.   Since each member function is in its own object module
  628. in the library, only those member functions actually used in  the
  629. application  are  linked  into the final executable image. To use
  630. CCC, the programmer specifies a library name, one or more  header
  631. files containing templates, and specific parameterized classes as
  632. command line arguments to CCC.  Other  arguments  are  passed  on
  633. unchanged  to the C++ compiler and system linker.  A single invo-
  634. cation of CCC can either process a parameterized  class  type  or
  635. compile a C++ source file, but not both.  For example,
  636.  
  637.         CCC -lapp -c List.h String.h -X "List<String>"
  638.  
  639. expands the template for a list of strings.  The resulting object
  640. files  from  the  fractured  parameterized  List<Type>  class are
  641. stored in the library, libapp.a.  The -c option is passed to  the
  642. compiler  to  indicate  that it should not continue with the link
  643. phase. The library archive libapp.a  is  added  to  the  list  of
  644. libraries  specified  in  the make file to be searched during the
  645. link step.
  646.  
  647. The net result is a library archive containing object files, each
  648.  
  649.                                      -11-
  650. implementing  one member function for the parameterized class and
  651. type. This process solves the two problems identified above  with
  652. the use of the macros DECLARE and IMPLEMENT. First, operators not
  653. defined for a type cause compile-time errors on  that  one  file.
  654. Once a parameterized class has been implemented and provided in a
  655. library, compile errors will only occur when a type  is  selected
  656. that  does  not  have  all operators implemented. The user of the
  657. class will see these, and if the member function in  question  is
  658. required, s/he can add that necessary operator to the type class.
  659. Second, only member functions actually used in an application are
  660. linked into the final executable image.
  661.  
  662. 4.4.  Future Improvements to CCC
  663. CCC essentially provides a  more  sophisticated  version  of  the
  664. IMPLEMENT macro discussed above. However, the programmer is still
  665. required to place the DECLARE macro  in  the  appropriate  files.
  666. One option under consideration to resolve this problem is the use
  667. of a command line switch similar to the +e0/+e1  switchs  on  the
  668. AT&T  cfront  translator.  Under this scenario, the equivalent of
  669. the +e0 option would be used to declare the type for a parameter-
  670. ized  class  and  generate  the  inline  member functions (as the
  671. DECLARE macro does) but not  to  generate  the  remaining  member
  672. functions.   The  programmer  would use the equivalent of the +e1
  673. option on one source  file  to  cause  the  remaining  non-inline
  674. member functions to be generated and placed in a library archive.
  675.  
  676. A second problem with CCC concerns the  specification  of  nested
  677. parameterized  classes.  A  programmer  should  be  able  to  use
  678. -X"Vector<List<int>>" on the command line to specify creation  of
  679. nested  parameterized  classes.   Currently,  CCC does not handle
  680. this case appropriately. A more sophisticated command line parser
  681. should  be  able  to  recognize and implement nested types before
  682. trying to expand the outer most parameterized class.
  683.  
  684. 5.  Conclusion
  685. The COOL macro facility provides a mechanism to implement  signi-
  686. ficant language features and extensions for C++ that are unavail-
  687. able with current language implementations.  The  macro  facility
  688. is implemented in an enhanced preprocessor that is both efficient
  689. and portable, thus allowing for  delivery  of  enhanced  language
  690. features  on many platforms. This macro extension is at the heart
  691. of the parameterized templates  functionality.  CCC  is  used  in
  692. place  of  the  normal  procedure for controlling the compilation
  693. process.  It provides all of the functionality of the original CC
  694. program  with  additional  support  for the COOL preprocessor and
  695. parameterized type expansion.  Finally, the preprocessor provides
  696. an ideal mechanism for quickly prototyping and testing additional
  697. language functions and syntax  without  requiring  access  to  or
  698. modification of a compiler.
  699.  
  700. 6.  Status of COOL
  701. Texas Instruments has been using the enhanced macro facility  and
  702. the  implementation  of  parameterized  templates  internally  on
  703. several projects for the last year.  Many  classes  and  programs
  704. have  been  successfully  designed  and  implemented, taking full
  705. advantage  of  the  power  of  parameterized  templates  and  the
  706. enhanced  macro  facility.  In particular, we have found that the
  707.  
  708.                                      -12-
  709. use of a class library supplying many  basic  parameterized  con-
  710. tainer  classes  significantly  increases the productivity of the
  711. programmer, enabling applications to be prototyped in  a  shorter
  712. time  period than might otherwise be possible.  COOL is currently
  713. up and running on a Sun SPARCstation 1 (TM)  running  SunOS  (TM)
  714. 4.x, a PS/2 (TM) model 70 running SCO XENIX(r) 2.3, a PS/2 model 70
  715. running  OS/2  1.1, and a MIPS running RISC/os 4.0. The SPARC and
  716. MIPS ports utilize the AT&T C++ translator (cfront)  version  2.0
  717. and  the XENIX and OS/2 ports utilize the Glockenspiel translator
  718. with the Microsoft C compiler.
  719.  
  720. 7.  References
  721. [1]  Brian  Kernighan  and  Dennis  Richie,  The  C   Programming
  722.      Language,  Second  Edition, Printice-Hill, Englewood Cliffs,
  723.      NJ, 1988.
  724. [2]  Mary Fontana, Martin Neath and Lamott Oren,  COOL  -  A  C++
  725.      Object-Oriented  Library, Information Technology Group, Aus-
  726.      tin, TX, Internal Original Issue January 1990.
  727. [3]  Texas Instruments Incorporated, C++ Object-Oriented  Library
  728.      User's  Manual,  Information  Technology  Group, Austin, TX,
  729.      Internal Original Issue January 1990.
  730. [4]  AT&T Incorporated, C++ Language  System  Release  2.0,  AT&T
  731.      Product Reference Manual Select Code 307-146, 1989.
  732. [5]  Guy L. Steele Jr, Common LISP: The Language, Second Edition,
  733.      1990.
  734. [6]  Bjarne Stroustrup, Parameterized Types for C++,  Proceedings
  735.      of  the  USENIX  C++  Conference, Denver, CO, October 17-21,
  736.      1988, pp. 1-18.
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.  
  757. _________________________
  758. SunOS and SPARCstation 1  are  trademarks  of  Sun  Mi-
  759. crosystems, Inc.
  760. PS/2 is a trademark of International Business  Machines
  761. Corporation.
  762. XENIX is a registered trademark of  Microsoft  Corpora-
  763. tion.
  764.  
  765.                                      -13-
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.                                      -14-
  825.  
  826.